﻿
//	------------------------------------------------------------------------------
//                                       _                          
//              _ __ ___   ___ _ __ ___ | |__  _ __ __ _ _ __   ___ 
//             | '_ ` _ \ / _ \ '_ ` _ \| '_ \| '__/ _` | '_ \ / _ \
//             | | | | | |  __/ | | | | | |_) | | | (_| | | | |  __/
//             |_| |_| |_|\___|_| |_| |_|_.__/|_|  \__,_|_| |_|\___|
//                                                     
//	------------------------------------------------------------------------------

#region - License -
//
//	------------------------------------------------------------------------------                                                   
//	         Copyright (c) 2010 Peter Vyvey (peter.vyvey@chiliware.be)
//	------------------------------------------------------------------------------
//
//
//	This file is part of CHILIWARE MEMBRANE.
//
//	CHILIWARE MEMBRANE is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Lesser General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	CHILIWARE MEMBRANE is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public License
//	along with CHILIWARE MEMBRANE.  If not, see <http://www.gnu.org/licenses/>.
//
//
#endregion

#region - Changes -
//
//	peter.vyvey@chiliware.be		2010-08-10		Created
//
#endregion

#region - Using -

using System;
using System.Collections.Concurrent;
using Chiliware.Membrane.Configuration;
using Chiliware.Membrane.Pattern.Creational;
using System.Collections.Generic;

#endregion

namespace Chiliware.Membrane.Model
{
	#region - SessionService.Session -

	internal sealed partial class SessionService : IDisposable
	{
		#region - Nested classes: SessionService.Session -

		/// <summary>
        /// A session containing pointers to secure services and repositories.
        /// </summary>
        internal sealed class Session : IDisposable
        {
            #region - Constructors -

            /// <summary>
            /// Default constructor.
            /// </summary>
            private Session()
                : base()
            {
                this.InitializeObject();
            }

            internal Session(string userID)
                : this()
            {
                this.UserID = userID;
				this.RegisterSession();
            }

            #endregion

            #region - Destructor -

            ~Session()
            {
                this.Dispose(false);
            }

            #endregion

            #region - Constants & static fields -

            /// <summary>
            /// The default session timeout value.
            /// </summary>
            internal static readonly TimeSpan TIMEOUT = new TimeSpan(0, 30, 0);

            #endregion

            #region - Private fields -

			/// <summary>
			/// TRUE if the object is disposed, FALSE otherwise.
			/// </summary>
			private bool isDisposed = false;

			/// <summary>
			/// The session registry service.
			/// </summary>
			private ISessionRegistryService sessionRegistryService;

            /// <summary>
            /// The hosted service instances.
            /// </summary>
			private readonly ConcurrentDictionary<Type, IApplicationService> services = new ConcurrentDictionary<Type, IApplicationService>();

            #endregion

            #region - Properties -

            /// <summary>
            /// The session's creator user identifier.
            /// </summary>
            public string UserID { get; private set; }

            /// <summary>
            /// Timestamp of the last activity for the session.
            /// </summary>
            internal DateTime LastActivity { get; private set; }

			/// <summary>
			/// The registered session ID.
			/// </summary>
			internal long SessionRegistryID
			{
				get { return this.sessionRegistryService.SessionRegistryID; }
			}

            #endregion

            #region - Public methods -

            /// <summary>
            /// Disposes the object.
            /// </summary>
            public void Dispose()
            {
				if (!this.isDisposed)
				{
					this.Dispose(true);
				}
                GC.SuppressFinalize(this);
            }


			/// <summary>
			/// Gets the parameters for the current session.
			/// </summary>
			/// <returns>The session parameters.</returns>
			internal Dictionary<string, string> GetSessionParameters()
			{
				return new Dictionary<string, string>();
			}

            /// <summary>
            /// Retreives a service of the specified type.
            /// </summary>
            /// <typeparam name="T">The service type.</typeparam>
            /// <returns>The service instance.</returns>
			internal T GetService<T>()
				where T : IApplicationService, new()
			{
				this.Touch();

				IApplicationService service = default(T);
				if (!this.services.TryGetValue(typeof(T), out service))
				{
					this.services[typeof(T)] = service = new T();
				}


				return (T)service;
			}

            #endregion

            #region - Private, protected & internal methods -

            /// <summary>
            /// Disposes managed and unmanaged resources.
            /// </summary>
            /// <param name="isDisposing">Flag indicating how this protected method was called. 
            /// TRUE means via Dispose(), FALSE means via the destructor.
            /// Only in case of a call through the Dispose() method should managed resources be freed.</param>
            private void Dispose(bool isDisposing)
            {
				if (!this.isDisposed)
				{
					if (null != this.sessionRegistryService)
					{
						this.sessionRegistryService.Dispose();
						this.sessionRegistryService = null;
					}
				}

				this.isDisposed = true;
            }

            /// <summary>
            /// Initializes the session.
            /// </summary>
            private void InitializeObject()
            {
                this.Touch();
            }

			/// <summary>
			/// Registers a session in the workspace backend.
			/// </summary>
			private void RegisterSession()
			{
				this.Touch();

				if (null != WorkspaceConfiguration.Configuration)
				{
					Configuration.Environment environment = WorkspaceConfiguration.Configuration.Host.Environments.GetEnabledEnvironment();

					// Configure the SESSIONREGISTRYSERVICE.
					Type sessionRegistryServiceType = Type.GetType(environment.SessionRegistryService.Type);
					this.sessionRegistryService = Activator.CreateInstance(sessionRegistryServiceType) as ISessionRegistryService;
					this.sessionRegistryService.Initialize(this.UserID);
				}
			}

            /// <summary>
            /// Updates the LastActivity timestamp.
            /// </summary>
            internal void Touch()
            {
                this.LastActivity = DateTime.UtcNow;
            }

            #endregion
        }

        #endregion
    }

    #endregion
}
